home *** CD-ROM | disk | FTP | other *** search
- /*
- ########## ICMPLIB_V1.h ##################################################
- ######################## ICMP Tunneling Library ##########################
- ####################################################### by FuSyS #########
-
- V.1 - NO (C)1998 FuSyS - TCP/IP Tools Unlimited
-
- **************************************************************************
- * COSA: Una libreria in standard C per sfruttare la possibilita' *
- * offerta dal protocollo ICMP di inserire dati all'interno *
- * del datagramma. *
- * *
- * CHI: individui dotati di una conoscenza base di C e TCP/IP *
- * che siano abbastanza fantasiosi da trovare un uso per *
- * questo tipo di codice. Se non avete questi requisiti, *
- * per favore impadronitevene prima di tornare a questa *
- * lib. *
- * *
- * OS: Linux 1.3.x e seguenti (raw sockets) *
- * *
- * TNX: Daemon9 e THC per i loro lavori *
- * *
- * LETTURE: TCP/IP Illustrated Vol.1 di R.W.Stevens, *
- * Project LOKI di Daemon9, *
- * /usr/include/*.h *
- **************************************************************************
-
- **************************************************************************
- * FUNZIONI *
- * *
- * void ICMP_init(void); - inizializza il tunnel ICMP - *
- * *
- * int ICMP_send(char *send_mesg, size_t mesglen, u_long dest_ip, *
- * int echo, int last); *
- * - invia i dati nel datagramma - *
- * send_mesg : dati da inviare *
- * mesglen : lunghezza di send_data *
- * dest_ip : l'IP cui mandare il datagramma *
- * echo : 1 se il datagramma contiene l'echo del *
- * server *
- * last : 1 se il datagramma e' l'ultimo di una *
- * serie *
- * *
- * int ICMP_sp_send(char *send_mesg, size_t mesglen, u_long dest_ip, *
- * u_long sp_ip); *
- * - invia spoofando l'IP sorgente - *
- * send_mesg : dati da inviare *
- * mesglen : lunghezza di send_data *
- * dest_ip : l'IP cui mandare il datagramma *
- * sp_ip : l'IP da spoofare *
- * *
- * int ICMP_recv(char *recv_mesg, size_t mesglen, int echo); *
- * - riceve il datagramma - *
- * recv_mesg : dati in ricezione *
- * mesglen : lunghezza di recv_data *
- * echo : 1 se riceviamo l'echo dal server *
- * *
- * void ICMP_reset(void); - resetta il tunnel ICMP - *
- * *
- *************************************************************************/
-
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <signal.h>
- #include <errno.h>
- extern int errno;
-
- #include <sys/types.h>
- #include <sys/time.h>
- #include <sys/param.h>
- #include <sys/socket.h>
- #include <sys/file.h>
- #include <netinet/in_systm.h>
- #include <netinet/in.h>
-
- #ifdef linux
- #include "linux_ip_icmp.h"
- #else
- #include <netinet/ip_icmp.h>
- #include <netinet/ip.h>
- #endif
-
- #include <arpa/inet.h>
- #include <netdb.h>
-
- #define ECHO_TAG 0xF001
- #define ECHO_LAST 0xF002
- #define REPLY 1
- #define LAST 1
- #define YEAH 1
- #define NOPE 0
-
- #define ICMP_HDR 8 /* 8-byte ICMP header */
- #define IP_HDR 20 /* 20-byte IP header */
- #define MAXMESG 4096 /* dati max*/
- #define MAXPACKET 5004 /* dimensioni max del pacchetto */
- /* ICMP_HDR + MAXMESG */
-
- int sockfd ;
- int ip_spoof ;
- u_long spoof_addr ;
- u_int icmp_init = 1 ;
- struct sockaddr_in clisrc;
-
- /************************************************************************
- * Funzioni per DNS e checksum - sempre le solite :) niente di nuovo qui *
- ************************************************************************/
-
- u_long nameResolve(char *hostname);
- char *hostLookup(u_long in);
- u_short in_chksum(u_short *ptr, int nbytes);
-
- u_long nameResolve(char *hostname)
- {
- struct in_addr addr;
- struct hostent *hostEnt;
-
- if((addr.s_addr=inet_addr(hostname)) == -1)
- {
- if(!(hostEnt=gethostbyname(hostname)))
- {
- fprintf(stderr,"Errore nella risoluzione del nome:`%s`\n",hostname);
- exit(0);
- }
- bcopy(hostEnt->h_addr,(char *)&addr.s_addr,hostEnt->h_length);
- }
- return addr.s_addr;
- }
-
- char *hostLookup(u_long in)
- {
- char hostname[1024];
- struct in_addr addr;
- struct hostent *hostEnt;
-
-
- bzero(&hostname,sizeof(hostname));
- addr.s_addr = in;
- hostEnt = gethostbyaddr((char *)&addr, sizeof(struct in_addr),AF_INET);
-
- if(!hostEnt)
- strcpy(hostname,inet_ntoa(addr));
- else
- strcpy(hostname,hostEnt->h_name);
-
- return(strdup(hostname));
- }
-
- u_short in_chksum(u_short *ptr, int nbytes)
- {
- register long sum; /* assumes long == 32 bits */
- u_short oddbyte;
- register u_short answer; /* assumes u_short == 16 bits */
-
- /*
- * Our algorithm is simple, using a 32-bit accumulator (sum),
- * we add sequential 16-bit words to it, and at the end, fold back
- * all the carry bits from the top 16 bits into the lower 16 bits.
- */
-
- sum = 0;
- while (nbytes > 1)
- {
- sum += *ptr++;
- nbytes -= 2;
- }
-
- /* mop up an odd byte, if necessary */
- if (nbytes == 1)
- {
- oddbyte = 0; /* make sure top half is zero */
- *((u_char *) &oddbyte) = *(u_char *)ptr; /* one byte only */
- sum += oddbyte;
- }
-
- /*
- * Add back carry outs from top 16 bits to low 16 bits.
- */
-
- sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */
- sum += (sum >> 16); /* add carry */
- answer = ~sum; /* ones-complement, then truncate to 16 bits */
-
- return((u_short) answer);
- }
-
- /************************************************************************
- ********************** Ed ora .... s_C_iotaim =;) ***********************
- ************************************************************************/
-
- void ICMP_init(void)
- {
- int spoof_opt = 1;
-
- if(icmp_init)
- {
- if (ip_spoof == NOPE) {
- if((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0 ) {
- fprintf(stderr, "Impossibile creare raw ICMP socket ");
- exit(0);
- }
- }
- if (ip_spoof == YEAH) {
- if((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0 ) {
- fprintf(stderr, "Impossibile creare raw socket ");
- exit(0);
- }
- if(setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &spoof_opt,
- sizeof(spoof_opt)) < 0 ) {
- fprintf(stderr,"Impossibile creare IP Header ");
- exit(0);
- }
- }
- icmp_init = 0;
- }
- }
-
- void ICMP_reset(void)
- {
- close(sockfd);
- icmp_init = 1;
- }
-
- int ICMP_send
- (char *send_mesg, size_t mesglen, u_long dest_ip, int echo, int last)
- {
- int sparato;
- struct tunnel {
- struct icmp icmp;
- u_char data[MAXMESG];
- } icmp_pk;
- int icmplen = sizeof(struct icmp);
- int pach_dim;
- struct sockaddr_in dest;
- int destlen;
-
- if(mesglen > MAXMESG)
- return(-1);
-
- if(icmp_init)
- ICMP_init();
-
- destlen = sizeof(dest);
- bzero((char *) &dest, destlen);
- dest.sin_family = AF_INET;
- dest.sin_addr.s_addr = dest_ip;
-
- pach_dim = mesglen + sizeof(struct icmp);
- memset(&icmp_pk, 0, pach_dim);
- icmp_pk.icmp.icmp_type = ICMP_ECHOREPLY;
- bcopy(send_mesg, icmp_pk.icmp.icmp_data, mesglen);
- icmp_pk.icmp.icmp_cksum = in_chksum((u_short *) &icmp_pk.icmp,
- (sizeof(struct icmp)+mesglen));
- if(echo) icmp_pk.icmp.icmp_seq = ECHO_TAG;
- if(last) icmp_pk.icmp.icmp_seq = ECHO_LAST;
-
- if( (sparato = sendto(sockfd, &icmp_pk, pach_dim, 0, (struct sockaddr *)
- &dest, destlen)) < 0 ) {
- perror("RAW ICMP SendTo: ");
- return(-1);
- }
- else if(sparato != pach_dim) {
- perror("Dimensioni pacchetto IP errate: ");
- return(-1);
- }
- return(sparato);
- }
-
- int ICMP_sp_send(char *send_mesg, size_t mesglen, u_long dest_ip, u_long sp_ip)
- {
- int sparato;
- struct spoof {
- struct ip ip;
- struct icmp icmp;
- u_char data[MAXMESG];
- } sp_pk;
- int iplen = sizeof(struct ip);
- int icmplen = sizeof(struct icmp);
- int pach_dim;
- struct sockaddr_in dest;
- int destlen;
-
- if(mesglen > MAXMESG)
- return(-1);
-
- if(icmp_init)
- ICMP_init();
-
- destlen = sizeof(dest);
- bzero((char *) &dest, destlen);
- dest.sin_family = AF_INET;
- dest.sin_addr.s_addr = dest_ip;
-
- pach_dim = mesglen + sizeof(struct ip) + sizeof(struct icmp);
- memset(&sp_pk, 0, pach_dim);
-
- sp_pk.ip.ip_v = 4;
- sp_pk.ip.ip_hl = 5;
- sp_pk.ip.ip_len = htons(iplen + icmplen + mesglen);
- sp_pk.ip.ip_ttl = 255;
- sp_pk.ip.ip_p = IPPROTO_ICMP;
- sp_pk.ip.ip_src.s_addr = sp_ip;
- sp_pk.ip.ip_dst.s_addr = dest_ip;
-
- sp_pk.icmp.icmp_type = ICMP_ECHOREPLY;
- bcopy(send_mesg, sp_pk.icmp.icmp_data, mesglen);
- sp_pk.icmp.icmp_cksum = in_chksum((u_short *) &sp_pk.icmp,
- (sizeof(struct icmp)+mesglen));
-
- if((sparato = sendto(sockfd, &sp_pk, pach_dim, 0, (struct sockaddr *)
- &dest, destlen)) < 0 ) {
- perror("RAW ICMP SendTo: ");
- return(-1);
- }
- if(sparato != pach_dim) {
- perror("Dimensioni pacchetto IP errate: ");
- return(-1);
- }
- return(sparato);
- }
-
- int ICMP_recv(char *recv_mesg, size_t mesglen, int echo)
- {
- struct recv {
- struct ip ip;
- struct icmp icmp;
- char data[MAXMESG];
- } rcv_pk;
- int pach_dim;
- int accolto;
- int iphdrlen;
- int clilen = sizeof(clisrc);
-
- if(icmp_init)
- ICMP_init();
-
- while(1)
- {
- pach_dim = mesglen + sizeof(struct ip) + sizeof(struct icmp);
- memset(&rcv_pk, 0, pach_dim);
- if( (accolto = recvfrom(sockfd, &rcv_pk, pach_dim, 0, (struct
- sockaddr *) &clisrc, &clilen)) < 0 )
- continue;
-
- iphdrlen = rcv_pk.ip.ip_hl << 2;
- if(accolto < (iphdrlen + ICMP_MINLEN))
- continue;
- accolto -= iphdrlen;
-
- if(!echo){
- if(!rcv_pk.icmp.icmp_id && !rcv_pk.icmp.icmp_code &&
- rcv_pk.icmp.icmp_type == ICMP_ECHOREPLY && rcv_pk.icmp.icmp_seq !=
- ECHO_TAG && rcv_pk.icmp.icmp_seq != ECHO_LAST)
- break;
- }
- if(echo){
- if(!rcv_pk.icmp.icmp_id && !rcv_pk.icmp.icmp_code &&
- rcv_pk.icmp.icmp_type == ICMP_ECHOREPLY
- && (rcv_pk.icmp.icmp_seq == ECHO_TAG || rcv_pk.icmp.icmp_seq ==
- ECHO_LAST) )
- break;
- }
- }
- if(!echo){
- accolto -= ICMP_HDR;
- bcopy(rcv_pk.icmp.icmp_data, recv_mesg, accolto);
- return(accolto);
- }
- if(echo){
- if(rcv_pk.icmp.icmp_seq == ECHO_TAG) {
- accolto -= ICMP_HDR;
- bzero(recv_mesg, sizeof(recv_mesg));
- bcopy(rcv_pk.icmp.icmp_data, recv_mesg, accolto);
- return(accolto);
- }
- return(-666);
- }
- }
-